package utils;

import java.io.File;
import java.util.*;

/*
 * 列出目录下(指定级别的)文件或目录
 * 级别表示从指定的目录开始最多搜索层数.层数从1开始
 * 默认层数为1(当前目录下), 如果想搜索所有层数中文件或目录,则指定一个大于255的数字就可以了(XP系统文件名的最大长度为256)
 * 
 */
public class ListSomeLevelDirsFiles implements Iterator<File>, Iterable<File> {
	public static final int MAX_LEVEL = Integer.MAX_VALUE;
	private File dir;
	int maxLevel; // 最多层数
	int currentLevel = 1; // 当前层数
	int index;
	List<File> dirs;

	public ListSomeLevelDirsFiles(String dirPath) {
		this(dirPath, 1);
	}

	public ListSomeLevelDirsFiles(File dir) {
		this(dir, 1);
	}

	public ListSomeLevelDirsFiles(String dirPath, int maxLevel) {
		this(new File(dirPath), maxLevel);
	}

	public ListSomeLevelDirsFiles(File dir, int maxLevel) {
		if (dir == null) {
			throw new NullPointerException();
		}

		if (maxLevel <= 0) {
			throw new IllegalArgumentException("maxLevel的值应大于等于1。");
		}

		this.dir = dir;
		this.maxLevel = maxLevel;
		init();

	}

	public void reset() {
		init();
	}

	void init() {

		if (dir.exists() && dir.isDirectory()) {
			dirs = new Vector<File>();
			dirs.addAll(Arrays.asList(dir.listFiles()));
			index = dirs.size() - 1;
		}else {
			throw new IllegalArgumentException(dir.getAbsolutePath() + "不存在或不是一个目录.");
		}
	}

	public boolean hasNext() {
		return dirs != null && !dirs.isEmpty();
	}

	public File next() {
		if (dirs != null && !dirs.isEmpty()) {
			File item = dirs.get(index);
			dirs.remove(index);
			if (item.isDirectory() && currentLevel < maxLevel) {
				// 对于System Volume Information目录, listFiles方法将返回null
				File[] files = item.listFiles();
				if (files != null) {
					dirs.addAll(Arrays.asList(item.listFiles()));
				}
			}
			--index;

			if (index < 0) {
				index = dirs.size() - 1;
				++currentLevel;
			}
			return item;
		} else {
			throw new NoSuchElementException();
		}
	}

	public void remove() {
		throw new UnsupportedOperationException();
	}

	@Override
	public Iterator<File> iterator() {
		reset();
		return this;
	}

	public static ListSomeLevelDirsFiles generateMaxLevelList(File file) {
		return new ListSomeLevelDirsFiles(file, Integer.MAX_VALUE);
	}
}
